package cn.uncode.baas.server.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import cn.uncode.baas.server.acl.Acl;
import cn.uncode.baas.server.acl.TableAcl;
import cn.uncode.baas.server.acl.token.AccessToken;
import cn.uncode.baas.server.dto.RestTable;
import cn.uncode.baas.server.exception.AuthorizationException;
import cn.uncode.baas.server.internal.context.RestContextManager;
import cn.uncode.baas.server.internal.message.Messages;

public class AccessTokenUtils {

    public static boolean checkPermissions(Acl acl, AccessToken token) {
        if (null == token) {
            return false;
        }
        if (null == token.getAdditionalInformation()) {
            return false;
        }
        boolean aclEnable = false;
        String bucket = (String) token.getAdditionalInformation().get(AccessToken.BUCKET);
        if (StringUtils.isNotEmpty(bucket) && !bucket.equals(RestContextManager.getContext().getBucket())) {
            return false;
        }
        if (StringUtils.isNotEmpty(bucket)) {
            if (!bucket.equals(RestContextManager.getContext().getBucket())) {
                return false;
            }
            /*
             * if(Resource.REST_SYSTEM_BUCKET_NAME.equals(bucket)){ String user
             * = (String)
             * token.getAdditionalInformation().get(AccessToken.USER);
             * if(!"admin".equals(user)){
             * if(!bucket.equals(RestContextManager.getContext().getBucket())){
             * return false; } } }else{
             */
            // }
        }
        List<String> groups = (List<String>) token.getAdditionalInformation().get(AccessToken.GROUP);
        List<String> roles = (List<String>) token.getAdditionalInformation().get(AccessToken.ROLE);
        if (null != acl.getGroups()) {
            for (String ac : acl.getGroups()) {
                if (groups.contains(ac)) {
                    aclEnable = true;
                    break;
                }
            }
        }
        if (aclEnable && null != acl.getRoles()) {
            for (String ac : acl.getRoles()) {
                if (roles.contains(ac)) {
                    aclEnable = true;
                    break;
                }
            }
        }
        return aclEnable;
    }

    /**
     * 
     * @param table
     * @param option
     * @return failed fields of authorization
     * @throws AuthorizationException
     */
    public static List<String> checkPermissions(RestTable table, String option) throws AuthorizationException {
        List<String> failFields = new ArrayList<String>();
        AccessToken accessToken = null;
        if (table != null && table.getAclOfTable() != null) {
            accessToken = RestContextManager.getContext().getToken();
            //write最高权限
            boolean check = false;
            if(null != table.getAclOfTable().getWrite()){
            	check = AccessTokenUtils.checkPermissions(table.getAclOfTable().getWrite(), accessToken);
    		}
            if(!check){
            	if (TableAcl.READ.equals(option)) {
                    if (table.getAclOfTable().getRead() != null) {
                        if (AccessTokenUtils.checkPermissions(table.getAclOfTable().getRead(), accessToken) == false) {
                            throw new AuthorizationException(Messages.getString("ValidateError.12"));
                        }
                    }
                } else {
                    if (TableAcl.INSERT.equals(option)) {
                        if (table.getAclOfTable().getInsert() != null) {
                            if (AccessTokenUtils.checkPermissions(table.getAclOfTable().getInsert(), accessToken) == false) {
                                throw new AuthorizationException(Messages.getString("ValidateError.13"));
                            }
                        }
                    } else if (TableAcl.UPDATE.equals(option)) {
                        if (table.getAclOfTable().getUpdate() != null) {
                            if (AccessTokenUtils.checkPermissions(table.getAclOfTable().getUpdate(), accessToken) == false) {
                                throw new AuthorizationException(Messages.getString("ValidateError.14"));
                            }
                        }
                    } else if (TableAcl.REMOVE.equals(option)) {
                        if (table.getAclOfTable().getRemove() != null) {
                            if (AccessTokenUtils.checkPermissions(table.getAclOfTable().getRemove(), accessToken) == false) {
                                throw new AuthorizationException(Messages.getString("ValidateError.15"));
                            }
                        }
                    }
                }
            }
        }
        if (table != null && StringUtils.isNotEmpty(table.getFieldAcl())) {
            Map<String, Acl> aclMap = new HashMap<String, Acl>();
            if (TableAcl.READ.equals(option)) {
            	if(null != table.getFieldWriteAcl()){
            		aclMap.putAll(table.getFieldWriteAcl());
            	}
            	if(null != table.getFieldReadAcl()){
            		aclMap.putAll(table.getFieldReadAcl());
            	}
            } else if (TableAcl.INSERT.equals(option)) {
            	if(null != table.getFieldWriteAcl()){
            		aclMap.putAll(table.getFieldWriteAcl());
            	}
            	if(null != table.getFieldInsertAcl()){
            		aclMap.putAll(table.getFieldInsertAcl());
            	}
            } else if (TableAcl.UPDATE.equals(option)) {
            	if(null != table.getFieldWriteAcl()){
            		aclMap.putAll(table.getFieldWriteAcl());
            	}
            	if(null != table.getFieldUpdateAcl()){
            		aclMap.putAll(table.getFieldUpdateAcl());
            	}
            }
            if (aclMap != null) {
                Iterator<String> iter = aclMap.keySet().iterator();
                while (iter.hasNext()) {
                    String key = iter.next();
                    if (AccessTokenUtils.checkPermissions(aclMap.get(key), accessToken) == false) {
                        failFields.add(key);
                    }
                }
            }
        }
        return failFields;
    }

}
